Weis Wave Volume Indicator

Table of Contents

Weis Wave Volume Indicator

Overview & Usage Strategy

About the Indicator

The Weis Wave Volume indicator is a powerful tool that organizes market volume into wave charts, clearly highlighting market inflection points and regions of supply and demand. Unlike traditional volume indicators that divide volume into equal time periods, Weis Wave focuses on natural price movements, providing a clearer picture of buying and selling pressure. The indicator was originally created by David Weis as an adaptation of Richard D. Wyckoff’s wave analysis method, designed to work with today’s volatile markets. It’s particularly effective at identifying potential turning points that might not be obvious on conventional bar charts.

Best Practices & Strategy Tips

Inputs and Options

Parameter Default Range Description
Trend Detection Length 2 ≥ 1 Controls wave consolidation. Higher values combine smaller waves, creating fewer but larger waves
Show Distribution Below Zero False True/False When enabled, displays downward waves below zero, creating an oscillator-like display

Formula

The core calculation logic works as follows:

1. Determine price movement direction (mov): 
   mov = 1 if close > previous close
   mov = -1 if close < previous close
   mov = 0 if no change

2. Identify trending conditions:
   is_trending = rising(close, trend_detection_length) OR falling(close, trend_detection_length)

3. Determine wave direction:
   wave = mov (if mov differs from previous wave AND is_trending)
   wave = previous wave (otherwise)

4. Calculate wave volume:
   vol = previous volume + current volume (if wave direction unchanged)
   vol = current volume (if wave direction changed)

5. Display result:
   res = vol (if showing absolute values)
   res = vol * wave direction (if showing distribution below zero)

Visualization / How to Interpret Values

The Weis Wave Volume indicator displays colored columns:

The height of each column represents the cumulative volume during that particular wave. Key patterns to look for:

Key Takeaways

Strengths:

Limitations:

Ideal Conditions:

Code Blocks: Key Implementation Logic

The most important Indie code elements for this indicator:

# Detect if price is rising for a specified number of bars
def rising(src: SeriesF, length: int) -> bool:
    for i in range(length):
        if not (src[i] > src[i + 1]):
            return False
    return True

# Detect if price is falling for a specified number of bars
def falling(src: SeriesF, length: int) -> bool:
    for i in range(length):
        if not (src[i] < src[i + 1]):
            return False
    return True

# Core Wave Calculation Logic
mov = 0
if self.close[0] > self.close[1]:
    mov = 1
elif self.close[0] < self.close[1]:
    mov = -1

is_trending = rising(self.close, trend_detection_length) or falling(self.close, trend_detection_length)

wave = MutSeriesF.new(0)
if mov != nan_to_zero(wave[1]) and is_trending:
    wave[0] = mov
else:
    wave[0] = nan_to_zero(wave[1])

vol = MutSeriesF.new(0)
if wave[0] == wave[1]:
    vol[0] = nan_to_zero(vol[1]) + self.volume[0]
else:
    vol[0] = self.volume[0]

Pine to Indie Comparison (for Indie language learners)

Let’s compare the key differences between Pine Script and Indie implementations:

Variable Declaration and Initialization

Pine Script:

mov = close>close[1] ? 1 : close<close[1] ? -1 : 0
trend = (mov != 0) and (mov != mov[1]) ? mov : nz(trend[1])

Indie:

mov = 0
if self.close[0] > self.close[1]:
    mov = 1
elif self.close[0] < self.close[1]:
    mov = -1

wave = MutSeriesF.new(0)
if mov != nan_to_zero(wave[1]) and is_trending:
    wave[0] = mov
else:
    wave[0] = nan_to_zero(wave[1])

Key Differences:

Series Handling

Pine Script:

wave=(trend != nz(wave[1])) and isTrending ? trend : nz(wave[1])
vol=wave==wave[1] ? (nz(vol[1])+volume) : volume

Indie:

wave = MutSeriesF.new(0)
if mov != nan_to_zero(wave[1]) and is_trending:
    wave[0] = mov
else:
    wave[0] = nan_to_zero(wave[1])

vol = MutSeriesF.new(0)
if wave[0] == wave[1]:
    vol[0] = nan_to_zero(vol[1]) + self.volume[0]
else:
    vol[0] = self.volume[0]

Key Differences:

Plotting

Pine Script:

plot(up, style=histogram, color=green, linewidth=3)
plot(dn, style=histogram, color=red, linewidth=3)

Indie:

@plot.columns(id='#plot_0')
# In the function:
return plot.Columns(res, color=col)

Key Differences:

Parameter Definition

Pine Script:

trendDetectionLength=input(2)
showDistributionBelowZero=input(false, type=bool)

Indie:

@param.int('trend_detection_length', default=2, min=1, title='Trend detection length')
@param.bool('show_distribution_below_zero', default=False, title='Show Distribution Below Zero')

Key Differences:

Full Source Code Templates

Indie Source Code (Full)

# For education purposes 
# Ported to Indie from https://www.tradingview.com/script/HFGx4ote-Indicator-Weis-Wave-Volume-LazyBear/
# The author of the original indicator is @LazyBear

# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.  
# If a copy of the MPL was not distributed with this file, you can obtain one at  
# <https://mozilla.org/MPL/2.0/>.

# indie:lang_version = 5
import math
from indie import indicator, SeriesF, MutSeriesF, param, plot, color


def rising(src: SeriesF, length: int) -> bool:
    for i in range(length):
        if not (src[i] > src[i + 1]):
            return False
    return True


def falling(src: SeriesF, length: int) -> bool:
    for i in range(length):
        if not (src[i] < src[i + 1]):
            return False
    return True


def nan_to_zero(val: float) -> float:
    return 0 if math.isnan(val) else val


@indicator('Weis Wave Volume')
@param.int('trend_detection_length', default=2, min=1, title='Trend detection length')
@param.bool('show_distribution_below_zero', default=False, title='Show Distribution Below Zero')
@plot.columns(id='#plot_0')
def Main(self, trend_detection_length, show_distribution_below_zero):
    mov = 0
    if self.close[0] > self.close[1]:
        mov = 1
    elif self.close[0] < self.close[1]:
        mov = -1

    is_trending = rising(self.close, trend_detection_length) or falling(self.close, trend_detection_length)

    wave = MutSeriesF.new(0)
    if mov != nan_to_zero(wave[1]) and is_trending:
        wave[0] = mov
    else:
        wave[0] = nan_to_zero(wave[1])

    vol = MutSeriesF.new(0)
    if wave[0] == wave[1]:
        vol[0] = nan_to_zero(vol[1]) + self.volume[0]
    else:
        vol[0] = self.volume[0]

    col = color.GREEN if wave[0] == 1 else color.RED
    res = vol[0]
    if show_distribution_below_zero:
        res = vol[0] * wave[0]

    return plot.Columns(res, color=col)

PineScript Source Code (Full)

//for education purposes
//indicator page https://www.tradingview.com/script/HFGx4ote-Indicator-Weis-Wave-Volume-LazyBear/
// @author LazyBear 
// List of all my indicators: https://www.tradingview.com/v/4IneGo8h/
//
study("Weis Wave Volume [LazyBear]", shorttitle="WWV_LB")
trendDetectionLength=input(2)
showDistributionBelowZero=input(false, type=bool)
mov = close>close[1] ? 1 : close<close[1] ? -1 : 0
trend= (mov != 0) and (mov != mov[1]) ? mov : nz(trend[1])
isTrending = rising(close, trendDetectionLength) or falling(close, trendDetectionLength) //abs(close-close[1]) >= dif
wave=(trend != nz(wave[1])) and isTrending ? trend : nz(wave[1])
vol=wave==wave[1] ? (nz(vol[1])+volume) : volume
up=wave == 1 ? vol : 0
dn=showDistributionBelowZero ? (wave == 1 ? 0 : wave == -1 ? -vol : vol) : (wave == 1 ? 0 : vol)
plot(up, style=histogram, color=green, linewidth=3)
plot(dn, style=histogram, color=red, linewidth=3)

License

MIT License Copyright (c) 2025